package persistence;

import org.hibernate.*;
import org.hibernate.engine.*;
import org.hibernate.usertype.*;
import org.hibernate.type.*;

import java.io.*;
import java.sql.*;
import java.math.*;
import java.util.*;
import hello.*;

public class MonetaryAmountCompositeUserType implements CompositeUserType
{            																						
	
	
	public Class returnedClass()
	{
		return MonetaryAmount.class;
	}
	
	public boolean isMutable()
	{
		return false;
	}
	
	public Object deepCopy(Object value)
	{
		return value;
	}
	
	public Serializable disassemble(Object value,SessionImplementor session)
	{
		return (Serializable)value;
	}
	
	public Object assemble(Serializable cached,SessionImplementor session,Object owner)
	{
		return cached;
	}
	
	public Object replace(Object original,Object target,SessionImplementor session,Object owner)
	{
		return original;
	}
	
	public boolean equals(Object x,Object y)
	{
		if(x == y)
			return true;
		if(x==null || y==null)
			return false;
		return x.equals(y);
	}
	
	public int hashCode(Object x)
	{
		return x.hashCode();
	}
	
	public Object nullSafeGet(ResultSet resultSet,String[] names,SessionImplementor session,Object owner)throws SQLException
	{//how to construct user type
		out("enter nullSafeGet:"+Arrays.asList(names)+"\t"+owner.getClass().getName());
		BigDecimal value =resultSet.getBigDecimal(names[0]);
		Currency c=Currency.getInstance(resultSet.getString(names[1]));
		return new MonetaryAmount(value,c);
	}
	
	public void nullSafeSet(PreparedStatement statement,Object value,int index,SessionImplementor session)throws HibernateException,SQLException
	{//how to persist user type
		if(value==null)
		{
			statement.setNull(index,Hibernate.BIG_DECIMAL.sqlType());
			statement.setNull(index+1,Hibernate.CURRENCY.sqlType());
			//statement.setNull(index,Hibernate.STRING.sqlType());
			out("enter nullSafeSet: set null to parameter:"+index);
		}else
		{
			MonetaryAmount amount=(MonetaryAmount)value;
			statement.setBigDecimal(index,amount.getAmount());
			statement.setString(index+1,amount.getCurrency().getCurrencyCode());
			//out("enter nullSafeSet: bind 555 to parameter:"+index);
		}
	}
	
	public String[] getPropertyNames(){
		return new String[]{"amount","currency"};
	}
	
	public Type[] getPropertyTypes()
	{
		return new Type[]{ Hibernate.BIG_DECIMAL,
											 Hibernate.CURRENCY };
	}
	
	public Object getPropertyValue(Object component,int property){
		out("###### enter getPropertyValue   "+property);
		String str=null;
		//str.length();
		MonetaryAmount ma=(MonetaryAmount)component;
		if(property==0)
			return ma.getAmount();
		else
			return ma.getCurrency();
	}
	
	public void setPropertyValue(Object componetn,int property,Object value){
		out("!!!!!!!!! enter setPropertyValue");
		throw new UnsupportedOperationException("Imutable...");
	}
	
	void out(Object obj)
	{
		System.out.println(this.getClass().getName()+"===>"+obj.toString());
	}
}